<template>
  <div class="upload-video">
    <div class="video-list">
      <div
        class="video-item"
        v-for="(item, index) in fileList"
        :key="item.uid"
        v-loading="item.status === 'uploading'"
      >
        <el-icon class="close" @click="onDelete(index)">
          <CircleClose />
        </el-icon>
        <video controls :src="item.url">您的浏览器不支持视频播放</video>
      </div>
    </div>

    <el-upload
      :class="{ hide: hideUpload }"
      drag
      accept="video/*"
      :action="action"
      :data="{ route: UPLOAD_DIR() }"
      :show-file-list="false"
      :file-list="fileList"
      :limit="limit"
      :before-upload="beforeUpload"
      :on-progress="onProgress"
      :on-success="onSuccess"
      :on-error="onError"
      :on-remove="onRemove"
      :disabled="disabled || isLoading"
    >
      <el-icon>
        <Plus />
      </el-icon>
    </el-upload>
  </div>
</template>

<script>
import { uploadUrl } from '@/api/upload'
import { UPLOAD_DIR } from '@/config/oss'
import { computed, watch, ref, reactive } from 'vue-demi'

export default {
  name: 'UploadVideo',
  props: {
    modelValue: Array,

    limit: {
      type: Number,
      default: 1
    },

    action: {
      type: String,
      default: uploadUrl
    },

    beforeUpload: Function,
    disabled: Boolean
  },
  emits: ['input', 'change', 'update:model-value'],
  setup (props, { emit }) {
    let fileList = reactive([])
    const isLoading = ref(false) // 是否上传中

    // 是否隐藏上传区域
    const hideUpload = computed(() => {
      if (props.limit === 0 || fileList.length >= props.limit) return true

      return false
    })

    watch(
      () => props.modelValue,
      (modelValue) => {
        if (!modelValue || !modelValue.length) {
          fileList.length = 0
          return false
        }

        modelValue.forEach((el, i) => {
          const file = {
            status: 'success',
            uid: Date.now() + i,
            url: el
          }
          fileList[i] = file
        })
      },
      { immediate: true, deep: true }
    )

    // 上传文件中回调
    const onProgress = (event, file, files) => {
      console.log(files.map(e => e.status))
      isLoading.value = true
    }

    // 上传文件成功回调
    const onSuccess = (res, file) => {
      const { code, data: { url } } = res
      const { uid } = file

      if (code === 200) {
        const index = fileList.findIndex(el => el.uid === uid)

        if (index === -1) {
          const i = { uid, url }
          fileList.push(i)
        } else {
          fileList[index].url = url
        }

        emitChange(fileList)
      }

      isLoading.value = false
    }

    // 上传文件失败回调
    const onError = () => {
      isLoading.value = false
    }

    // 移除文件回调
    const onRemove = (_, files) => {
      fileList = reactive(files)
      emitChange(fileList)
    }

    // 手动移除文件
    const onDelete = (i) => {
      fileList.splice(i, 1)

      emitChange(fileList)
    }

    // 文件列表数据改变事件分发
    const emitChange = (value) => {
      const urls = value.map(el => el.url)

      emit('change', urls)
      emit('input', urls)
      emit('update:model-value', urls)
    }

    return {
      UPLOAD_DIR,
      fileList,
      isLoading,
      hideUpload,
      onProgress,
      onSuccess,
      onError,
      onRemove,
      onDelete
    }
  }
}
</script>

<style lang="scss" scoped>
.upload-video {
  :deep(.el-upload) {
    position: relative;
    width: 96px;
    height: 96px;
    border: none;
    .el-upload-dragger {
      position: absolute;
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      .el-icon-upload {
        margin: 0;
        font-size: 40px;
      }
    }
  }

  .hide {
    display: none;
  }

  .video-list .video-item {
    width: 400px;
    height: 200px;
    position: relative;
    line-height: 0;
    video {
      width: 100%;
      height: 100%;
    }
    .close {
      position: absolute;
      top: 10px;
      right: 10px;
      z-index: 2;
      font-size: 30px;
      color: #ccc;
      cursor: pointer;
      &:hover {
        color: #fff;
      }
    }
  }
}
</style>
